﻿using System.Dynamic;

namespace Agile.DataAccess
{
    /// <summary>
    /// 
    /// </summary>
    internal partial class DbContext
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IQueryBuilder<T> Builder<T>()
        {
            return new QueryBuilder<T>(CreateCommand);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public ISelectBuilder Select(string tableName)
        {
            return new SelectBuilder(CreateCommand, tableName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public ISelectBuilder<T> Select<T>(string tableName)
        {
            return new SelectBuilder<T>(CreateCommand, tableName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public IInsertBuilder Insert(string tableName)
        {
            return new InsertBuilder(CreateCommand, tableName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IInsertBuilder<T> Insert<T>(T item, string tableName)
        {
            return new InsertBuilder<T>(CreateCommand, tableName, item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IInsertBuilderDynamic Insert(string tableName, ExpandoObject item)
        {
            return new InsertBuilderDynamic(CreateCommand, tableName, item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public IUpdateBuilder Update(string tableName)
        {
            return new UpdateBuilder(Data.FluentDataProvider, CreateCommand, tableName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IUpdateBuilder<T> Update<T>(T item, string tableName)
        {
            return new UpdateBuilder<T>(Data.FluentDataProvider, CreateCommand, tableName, item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IUpdateBuilderDynamic Update(string tableName, ExpandoObject item)
        {
            return new UpdateBuilderDynamic(Data.FluentDataProvider, CreateCommand, tableName, item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public IDeleteBuilder Delete(string tableName)
        {
            return new DeleteBuilder(CreateCommand, tableName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IDeleteBuilder<T> Delete<T>(T item, string tableName)
        {
            return new DeleteBuilder<T>(CreateCommand, tableName, item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public IExistsBuilder Exists(string tableName)
        {
            return new ExistsBuilder(CreateCommand, tableName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IExistsBuilder<T> Exists<T>(T item, string tableName)
        {
            return new ExistsBuilder<T>(CreateCommand, string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName, item);
        }

        /// <summary>
        /// 
        /// </summary>
        private void VerifyStoredProcedureSupport()
        {
            if (!Data.FluentDataProvider.SupportsStoredProcedures)
                throw new FluentDataException("The selected database does not support stored procedures.");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="storedProcedureName"></param>
        /// <returns></returns>
        public IStoredProcedureBuilder Procedure(string storedProcedureName)
        {
            VerifyStoredProcedureSupport();
            return new StoredProcedureBuilder(CreateCommand, storedProcedureName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storedProcedureName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IStoredProcedureBuilder<T> Procedure<T>(T item, string storedProcedureName)
        {
            VerifyStoredProcedureSupport();
            return new StoredProcedureBuilder<T>(CreateCommand, storedProcedureName, item);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="storedProcedureName"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public IStoredProcedureBuilderDynamic Procedure(string storedProcedureName, ExpandoObject item)
        {
            VerifyStoredProcedureSupport();
            return new StoredProcedureBuilderDynamic(CreateCommand, storedProcedureName, item);
        }

    }
}
